package com.deyuanyun.pic.settings.support.interceptor;

import com.deyuanyun.pic.common.util.CommonUtil;
import com.deyuanyun.pic.common.util.HardWareUtils;
import com.deyuanyun.pic.settings.controller.dto.UserSessionVO;
import com.deyuanyun.pic.settings.controller.dto.org.CompanyDTO;
import com.deyuanyun.pic.settings.controller.dto.org.CompanyVO;
import com.deyuanyun.pic.settings.controller.dto.prvlg.UserVO;
import com.deyuanyun.pic.settings.domain.greatwall.LogUser;
import com.deyuanyun.pic.settings.domain.greatwall.ProductLog;
import com.deyuanyun.pic.settings.domain.prvlg.Menu;
import com.deyuanyun.pic.settings.mapper.prvlg.MenuMapper;
import com.deyuanyun.pic.settings.service.greatwall.LogUserService;
import com.deyuanyun.pic.settings.service.greatwall.ProductLogService;
import com.deyuanyun.pic.settings.service.org.CompanyService;
import com.deyuanyun.pic.settings.support.base.ApplicationPropertiesListener;
import com.deyuanyun.pic.settings.support.cache.SessionCacheSupport;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 日志记录拦截器
 *  @author axiao(xj08.dream@gmail.com)
 *  @date 2016-12-21
 *  @version 1.0
 *  Histroy: [修改人][时间][描述]
 */
public class SpringInterceptor implements HandlerInterceptor, InitializingBean, DisposableBean {
    private static Logger log = LogManager.getLogger(HandlerInterceptor.class);

    private String[] excludes;
    public String[] getExcludes() {
        return excludes;
    }

    public void setExcludes(String[] excludes) {
        this.excludes = excludes;
    }

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private LogUserService logUserService;

    @Autowired
    private ProductLogService productLogService;

    //大url地址和菜单id的对应关系
    private Map<String,String> urlIdMap = RequestAndResponseInterceptor.urlIdMap;

    private  Map<String, Menu> menuIdMap = new HashMap<String, Menu>(); //所有菜单，以菜单id为key

    private Map<String, Menu> menuUrlMap = new HashMap<String, Menu>(); //所有菜单，以菜单url为key，一级菜单不要，url为空不要，父级id为空不要

    private ExecutorService executor = null;

    @Override
    public void destroy() throws Exception {
        if(executor != null) {
            executor.shutdownNow();
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        executor =  Executors.newSingleThreadExecutor();
        List<Menu> menuList = menuMapper.querySameLevelMenu("", "");;
        if(menuList != null) {
            Iterator<Menu> menuIterator = menuList.iterator();
            Menu menu = null;
            while (menuIterator.hasNext()) {
                menu = menuIterator.next();
                String url = menu.getUrl();
                if(menu.getLevel() > 1 && StringUtils.isNotEmpty(menu.getParentId()) && StringUtils.isNotEmpty(url)) {
                    menuUrlMap.put(url, menu);
                }
                menuIdMap.put(menu.getId(), menu);
            }
        }
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        String requestUrl = request.getRequestURI();
        if(requestUrl.indexOf(".json") > 0) { //ajax请求不拦截
            return;
        }
        requestUrl = requestUrl.replaceAll("//", "/");
        requestUrl = StringUtils.removeStart(requestUrl, request.getContextPath());
        String menuId = urlIdMap.get(StringUtils.substringBetween(requestUrl,"/","/"));
        Menu menu = menuUrlMap.get(requestUrl);
        if(menu != null) {
            accessStatistics(requestUrl, menuId, menu);
        }
    }


    /**
     *
     * @param code 唯一编号
     * @param accessUrl 访问的url
     * @param userId 用户id
     * @param accessTitle 当前访问url对应的模块里面的一级菜单名
     * @return
     * @author axiao(xj08.dream@gmail.com)
     * @date 2016-12-20
     */
    private ProductLog getProductLog(String code, String accessUrl, String userId, String accessTitle) {
        ProductLog productLog = new ProductLog();
        productLog.setId(CommonUtil.getUUID());
        productLog.setCreateDate(new Date());
        String ip = HardWareUtils.getWebIP(); //外网ip
        if(StringUtils.isEmpty(ip)) {
            ip = HardWareUtils.getLocalIP();
        }
        productLog.setServerIp(ip);
        productLog.setServciceHardDiskSn(HardWareUtils.getHardDiskSN());
        productLog.setServiceCpuSerial(HardWareUtils.getCPUSerial());
        productLog.setServiceMac(HardWareUtils.getMacAddress());
        productLog.setServiceMotherboardSn(HardWareUtils.getMotherboardSN());
        productLog.setCode(code);
        productLog.setAccessUrl(accessUrl);
        productLog.setUserId(userId);
        productLog.setAccessUrlTitle(accessTitle);
        productLog.setAccessUrlCount(1L);
        return productLog;
    }

    private void accessStatistics(final String requestUrl, final String menuId, final Menu menu) {
        final UserSessionVO userSessionVO = SessionCacheSupport.getSessionVO();
        executor.execute(new Runnable() {
            @Override
            public void run() {
                Menu m = menu;
                try {
                    String menuTitle = "";
                    if (menuId.equals(menu.getParentId())) {
                        menuTitle = menu.getShowName();
                    } else {
                        while (true) { //取得菜单名字
                            m = menuIdMap.get(m.getParentId());
                            if (menuId.equals(m.getParentId())) {
                                menuTitle = m.getShowName();
                                break;
                            }
                        }
                    }
                    List<CompanyDTO> companyDTOS = companyService.queryCacheAll();
                    Map<String, CompanyDTO> companyMap = new HashMap<String, CompanyDTO>();
                    CompanyDTO companyDTO = null;
                    for (int i = 0, len = companyDTOS.size(); i < len; i++) {
                        companyDTO = companyDTOS.get(i);
                        companyMap.put(companyDTO.getId(), companyDTO);
                    }
                    String companyName = null; //公司名称
                    UserVO userVO = userSessionVO.getUserDetailInfo();
                    String companyId = userVO.getCompanyId();
                    if (StringUtils.isNotEmpty(companyId)) {
                        companyDTO = companyMap.get(companyId);
                        String parentCompanyId = companyDTO.getParentId();
                        while (StringUtils.isNotEmpty(parentCompanyId)) {
                            companyDTO = companyMap.get(companyId);
                            parentCompanyId = companyDTO.getParentId();
                        }
                        companyName = companyDTO.getShortName();
                    }
                    String userName = userVO.getRealName(); //用户真实名字
                    if (StringUtils.isEmpty(userName)) { //内置账号莫得真实姓名，所以这里取登录名
                        userName = userVO.getUsername();
                    }
                    String code = ApplicationPropertiesListener.code;

                    LogUser logUser2 = logUserService.selectByCodeAndName(code, userName);

                    if (logUser2 != null) { //存在记录，更新
                        String logUserId = logUser2.getId();
                        ProductLog productLog = productLogService.selectByUserIdAndCode(logUserId, code, requestUrl);
                        if (productLog != null) { //存在记录更新访问次数
                            Long urlCount = productLog.getAccessUrlCount();
                            if(urlCount != null) {
                                urlCount++;
                            }
                            productLog.setAccessUrlCount(urlCount);
                            productLogService.updateByPrimaryKeySelective(productLog);
                        } else { //不存在插入数据
                            productLog = getProductLog(code, requestUrl, logUserId, menuTitle);
                            productLogService.insertSelective(productLog);
                        }
                    } else { //不存在记录，插入
                        String sex = userVO.getSex(); //性别
                        String department = userVO.getDepartment(); //部门
                        String position = userVO.getPosition(); //岗位
                        String mobile = userSessionVO.getMoblie(); //手机号码
                        String email = userSessionVO.getEmail(); //邮箱
                        String id = CommonUtil.getUUID();
                        LogUser logUser = new LogUser();
                        logUser.setCreateDate(new Date());
                        logUser.setId(id);
                        logUser.setSex(sex);
                        logUser.setDeptName(department);
                        logUser.setEmail(email);
                        logUser.setPostName(position);
                        logUser.setMobile(mobile);
                        logUser.setUserName(userName);
                        logUser.setCompanyName(companyName);
                        logUser.setCode(code);
                        logUserService.insertSelective(logUser);
                        ProductLog productLog = getProductLog(code, requestUrl, id, menuTitle);
                        productLogService.insertSelective(productLog);
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
        });
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    }
}
